<template>
  <div class="map-wrapper">
    <div id="mapcontainer" />
    <div class="search-box">
      <el-autocomplete
        v-model="keyword"
        :fetch-suggestions="handleSearch"
        :trigger-on-focus="false"
        clearable
        placeholder="输入城市+关键字搜索"
        style="width: 300px"
        @select="handleSelect"
      />
      <el-input
        v-model="location.longitude"
        placeholder="点击地图选择经度"
        maxlength="15"
        readonly
        style="width: 150px; margin: 0 5px"
      />
      <el-input
        v-model="location.latitude"
        placeholder="点击地图选择纬度"
        maxlength="15"
        readonly
        style="width: 150px"
      />
      <el-input
        v-model="location.address"
        placeholder="选中地点"
        readonly
        style="width: 400px; margin-left: 10px"
      />
    </div>
    <div style="display: flex; justify-content: end; padding: 20px 50px">
      <el-button type="success" @click="readyLoactionBack">
        店铺地址确认
      </el-button>
      <el-button type="primary" @click="resetLoaction">重绘地图</el-button>
    </div>
  </div>
</template>

<script setup>
  import {
    defineEmits,
    onMounted,
    shallowRef,
    computed,
    watch,
    ref,
    getCurrentInstance,
  } from 'vue'
  import AMapLoader from '@amap/amap-jsapi-loader'
  window._AMapSecurityConfig = {
    securityJsCode: 'c6d14eb1523e18e1f962f8b0b86d4e2b',
  }

  const {
    proxy: { $forceUpdate },
  } = getCurrentInstance()
  const props = defineProps({
    modelValue: {
      type: Object,
      default() {
        return {
          longitude: null,
          latitude: null,
          address: '',
          zone: ['', '', ''],
          name: '',
        }
      },
    },
    latitude: {
      type: String || Number,
      default: () => null,
    },
    longitude: {
      type: String || Number,
      default: () => null,
    },
  })
  const emit = defineEmits(['update:modelValue', 'redayLoaction'])
  const map = shallowRef(null)
  // 地点
  const location = computed({
    get() {
      return props.modelValue
    },
    set(val) {
      emit('update:modelValue', val)
    },
  })
  watch(location, (val) => {
    if (val.longitude && val.latitude) {
      drawMarker()
    }
  })
  const keyword = ref('')
  let placeSearch, AMapObj, marker, geocoder
  function initMap() {
    AMapLoader.load({
      key: '9b7e60c8eb6956aae94d4bb78482916a', // 申请好的Web端Key，首次调用 load 时必填
      version: '2.0',
    }).then(async (AMap) => {
      AMapObj = AMap
      map.value = new AMap.Map('mapcontainer', await echoMap())
      // 添加点击事件
      map.value.on('click', onMapClick)
      if (location.value.longitude) {
        drawMarker()
      }
      AMap.plugin(
        [
          'AMap.ToolBar',
          'AMap.Scale',
          'AMap.Geolocation',
          'AMap.PlaceSearch',
          'AMap.Geocoder',
        ],
        () => {
          // 缩放条
          const toolbar = new AMap.ToolBar()
          // 比例尺
          const scale = new AMap.Scale()
          // 定位
          const geolocation = new AMap.Geolocation({
            enableHighAccuracy: true, // 是否使用高精度定位，默认:true
            timeout: 10000, // 超过10秒后停止定位，默认：5s
            position: 'RT', // 定位按钮的停靠位置
            buttonOffset: new AMap.Pixel(10, 20), // 定位按钮与设置的停靠位置的偏移量，默认：Pixel(10, 20)
            zoomToAccuracy: true, // 定位成功后是否自动调整地图视野到定位点
          })
          geocoder = new AMap.Geocoder({
            city: '全国',
          })
          if (props.latitude && props.longitude) {
            onMapClick({
              lnglat: {
                lng: parseFloat(props.longitude),
                lat: parseFloat(props.latitude),
              },
            })
          }

          map.value.addControl(geolocation)
          map.value.addControl(toolbar)
          map.value.addControl(scale)
          placeSearch = new AMap.PlaceSearch({
            map: map.value,
            city: '',
            pageSize: 30, // 单页显示结果条数
            pageIndex: 1, // 页码
            citylimit: false, // 是否强制限制在设置的城市内搜索
            autoFitView: true,
          })
        }
      )
    })
  }
  onMounted(async () => {
    await initMap()
  })

  // 回显地图处理
  const echoMap = async () => {
    if (props.latitude && props.longitude) {
      return {
        center: [parseFloat(props.longitude), parseFloat(props.latitude)], // 初始地图中心点经纬度
        zoom: 15, // 初始地图缩放级别
      }
    }
    return {
      center: [113.259249, 23.127185], // 初始地图中心点经纬度
      zoom: 13, // 初始地图缩放级别
    }
  }

  // 搜索地图
  function handleSearch(queryString, cb) {
    placeSearch.search(queryString, (status, result) => {
      if (result && typeof result === 'object' && result.poiList) {
        const list = result.poiList.pois
        list.forEach((item) => {
          item.value = item.name
          item.label = item.name
        })
        cb(list)
      } else {
        cb([])
      }
    })
  }
  // 点击地图
  function onMapClick(e) {
    const { lng, lat } = e.lnglat
    // 逆地理编码
    geocoder.getAddress([lng, lat], (status, result) => {
      if (status === 'complete' && result.info === 'OK') {
        const { addressComponent, formattedAddress } = result.regeocode
        let { city, province, district } = addressComponent
        if (!city) {
          // 直辖市
          city = province
        }
        Object.assign(location.value, {
          longitude: lng,
          latitude: lat,
          address: formattedAddress,
          zone: [province, city, district],
          name: '',
        })
        $forceUpdate()
      }
    })
  }
  // 点击搜索项
  function handleSelect(item) {
    const { pname, cityname, adname, address, name } = item
    const { lng, lat } = item.location
    const newaddress = pname + cityname + adname + address
    Object.assign(location.value, {
      longitude: lng,
      latitude: lat,
      address: newaddress,
      zone: [pname, cityname, adname],
      name,
    })
    map.value.setZoomAndCenter(16, [lng, lat])
    $forceUpdate()
  }
  // 绘制地点marker
  function drawMarker(val) {
    const { longitude, latitude } = location.value || val
    if (marker) {
      marker.setMap(null)
    }
    marker = new AMapObj.Marker({
      position: new AMapObj.LngLat(longitude, latitude),
      anchor: 'bottom-center',
    })
    map.value.add(marker)
    map.value.setZoomAndCenter(16, [longitude, latitude])
  }

  const readyLoactionBack = () => {
    emit('redayLoaction', location.value)
  }

  const resetLoaction = async () => {
    Object.assign(location.value, {
      longitude: null,
      latitude: null,
      address: '',
      zone: ['', '', ''],
      name: '',
    })
    await initMap()
    $forceUpdate()
  }

  defineExpose({ resetLoaction })
</script>

<style lang="scss" scoped>
  .map-wrapper {
    position: relative;
    width: 100%;
    height: 550px;

    #mapcontainer {
      width: 100%;
      height: 100%;
    }

    .search-box {
      position: absolute;
      top: 10px;
      left: 10px;
      z-index: 1;
      display: flex;
      align-items: center;
    }
  }
</style>
